#include <page.h>
#include <app.h>
#include <task.h>

/******************************************************************************
* 函数名称: void ClearPageWR(void)
* 功能说明: 清内核页表项 WR 位
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 页表项属性 WR=0，表示 3 特权级无法修改该页表项对应的物理内存页
******************************************************************************/
void ClearKernelPageWR(void)
{
    U32* TblBase = (U32 *)PAGE_TAB_BASE;        // 页表项本身所在的物理内存基地址
    U32 index = APP_START_ADDR / 0x1000 - 1;    // APP_START_ADDR = 0x80000: APP 加载地址
    U32 i = 0;
    U32 value = 0;

    // 遍历应用程序起始地址以下的内存所对应的页表项（我们认为应用程序起始地址以下的内存空间为内核空间）
    // 将其中 RW 位（bit1）置 0，在 3 特权级下无法对对应的物理页进行写操作（只读）
    for(i = 0; i <= index; i++)
    {
        value = *TblBase;
        value &= 0xFFFFFFFD;
        *TblBase = value;
        TblBase++;
    }

    // 更改页表后最好刷新一下页表，所谓的刷新页表其实就是将页目录项基址重新写一遍到 cr3 寄存器中
    asm volatile(
                "movl %0,   %%eax\n"
                "movl %%eax,  %%cr3\n"
                :
                : "a"(PAGE_DIR_BASE) // %0 替换成 PAGE_DIR_BASE
                :
                );
}

/******************************************************************************
* 函数名称: void PageFault(U32 err_code)
* 功能说明: 页异常中断服务程序
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
void PageFaultHandle(void)
{
    TaskDestory();
}